<template>
  <div>
    <el-form :model="form" label-width="110px" ref="formRef" class="form el-row">
      <el-col v-for="key in keys" :key="key" :span="search_data[key].colSpan || 24">
        <el-form-item :label="$t(search_data[key].name)" :prop="key">
          <el-input
            v-if="search_data[key].type === 'text'"
            :title="key"
            v-model="form[key]"
            autocomplete="off"
            clearable
            :placeholder="$t('pleaseInput')"
            :maxlength="search_data[key].maxlength"
            :show-word-limit="true"
          ></el-input>
          <el-select
            v-if="search_data[key].type === 'select'"
            clearable
            :filterable="search_data[key].filterable || false"
            v-model="form[key]"
            @change="handleChange($event, key)"
            class="size"
          >
            <el-option
              v-for="item in search_data[key].items"
              :key="item.key"
              :value="item.key"
              :label="item.name"
            >
            </el-option>
          </el-select>
          <el-date-picker
            v-if="search_data[key].type === 'date'"
            v-model="form[key]"
            type="datetimerange"
            align="right"
            unlink-panels
            :range-separator="$t('to')"
            :start-placeholder="$t('start_time')"
            :end-placeholder="$t('end_time')"
            :shortcuts="search_data[key].unPickerOptions ? [] : shortcuts"
            value-format="YYYY-MM-DD HH:mm:ss"
            :default-time="defaultTime"
          >
          </el-date-picker>
          <virtual-list
            v-if="search_data[key].type === 'virtual_list'"
            :value="form[key]"
            class="size"
            :list="search_data[key].items"
            @selectValue="handleSelect(key, $event)"
          ></virtual-list>
          <el-cascader
            v-if="search_data[key].type === 'cascader'"
            v-model="form[key]"
            ref="cascaderRef"
            class="size"
            :options="search_data[key].options"
            @change="handleCascaderChange(key, $event)"
            :props="{
              checkStrictly: search_data[key].param.flag,
              expandTrigger: 'hover',
              children: search_data[key].param.children,
              value: search_data[key].param.value,
              label: search_data[key].param.label,
            }"
            clearable
            filterable
          ></el-cascader>
        </el-form-item>
      </el-col>
    </el-form>
    <slot name="footer">
      <div class="dialog-footer">
        <el-button @click="handleCancel">{{ $t('cancel') }}</el-button>
        <el-button class="kylin-button" @click="handleReset">{{ $t('Reset') }}</el-button>
        <el-button class="kylin-button" @click="handleSearch">{{ $t('Search') }}</el-button>
      </div>
    </slot>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, watch, useTemplateRef } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import type { FormInstance, CascaderInstance } from 'element-plus';
import { noop } from '@/utils/index';
import VirtualList from '@/components/VirtualList/index.vue';

const { t } = useI18n();
const $route = useRoute();

const props = defineProps({
  search_data: {
    type: Object,
    required: true,
  },
  display: {
    type: Boolean,
    default: false,
  },
  modalTable: {
    type: Boolean,
    default: false,
  },
  modalSearch: {
    type: String,
    default: '',
  },
});

const emit = defineEmits<{
  click: [];
  search: [string, Record<string, any>];
  reset: [];
}>();

const form = ref<Record<string, any>>({});
const shortcuts = ref([
  {
    text: t('last_week'),
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setDate(start.getDate() - 7);
      return [start, end];
    },
  },
  {
    text: t('last_month'),
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setMonth(start.getMonth() - 1);
      return [start, end];
    },
  },
  {
    text: t('last_three_month'),
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setMonth(start.getMonth() - 3);
      return [start, end];
    },
  },
]);
const keys = ref<string[]>([]);
const defaultTime: [Date, Date] = [new Date(2025, 4, 1, 0, 0, 0), new Date(2025, 5, 1, 23, 59, 59)];

// 定义模板引用
const formRef = useTemplateRef<FormInstance | null>('formRef');
const cascaderRef = useTemplateRef<CascaderInstance | null | Array<CascaderInstance>>(
  'cascaderRef',
);

onMounted(() => {
  Object.keys(props.search_data).forEach((key: string) => {
    keys.value.push(key);
    if (props.search_data[key].func) {
      props.search_data[key].func();
    }
  });
  setForm();
});

const handleSelect = (key: string, value: any) => {
  form.value[key] = value;
};

const handleCascaderChange = (key: string, value: any[]) => {
  // checkStrictly 为true 不会自动收起列表
  if (props.search_data[key].param?.flag && value && value[0]) {
    // 因为有的toggleDropDownVisible可以直接调用，有的在对象里
    if (Array.isArray(cascaderRef.value)) {
      cascaderRef.value[0].togglePopperVisible(false);
    } else {
      cascaderRef.value?.togglePopperVisible(false);
    }
  }
};

const handleChange = (value: any, key: string) => {
  props.search_data[key].watch ? props.search_data[key].watch.call(null, value) : noop();
};

const handleCancel = () => {
  emit('click');
};

const handleSearch = () => {
  let search = '';
  Object.keys(form.value).forEach((key) => {
    let rule = '';
    // 对 cascader 类型单独处理
    if (props.search_data[key].type === 'cascader' && form.value[key]) {
      if (Array.isArray(form.value[key])) {
        form.value[key].length > 0
          ? (rule = `${key} = "${form.value[key][form.value[key].length - 1]}"`)
          : null;
      } else {
        rule = `${key} = "${form.value[key]}"`;
      }
    } else if (Array.isArray(form.value[key]) && props.search_data[key].type !== 'cascader') {
      if (form.value[key][0] && form.value[key][1]) {
        rule = `${key} >= "${form.value[key][0]}" and ${key} <= "${form.value[key][1]}"`;
      }
    } else {
      // query 为 true 查询方法是“=”，否则为“~”
      if (form.value[key] || form.value[key] === false || form.value[key] === 0) {
        if (props.search_data[key].query) {
          rule = `${key} = "${form.value[key]}"`;
        } else {
          rule = `${key} ~ "${form.value[key]}"`;
        }
      }
    }
    if (search === '') {
      search = rule;
    } else {
      if (rule) {
        search = search + ` and ${rule}`;
      }
    }
  });
  if (search !== '') {
    search = '@{' + search + '}';
  }
  emit('search', search, form.value);
};

const handleReset = () => {
  form.value = {};
  formRef.value?.resetFields();
  emit('reset');
};

const setForm = () => {
  let search = props.modalSearch;

  if (!props.modalTable) {
    search = ($route.query.search as string) || '';
  }

  const formData: Record<string, any> = {};
  keys.value.forEach((key) => {
    if (props.search_data[key].type === 'date') {
      const regStart = new RegExp(`${key} >= "(.*?)"`);
      const regEnd = new RegExp(`${key} <= "(.*?)"`);
      formData[key] = [];
      const startMatch = regStart.exec(search);
      if (startMatch) {
        formData[key].push(startMatch[1]);
      }
      const endMatch = regEnd.exec(search);
      if (endMatch) {
        formData[key].push(endMatch[1]);
      }
    } else {
      formData[key] = '';
      const reg = new RegExp(`${key} ~ "(.*?)"`);
      const reg2 = new RegExp(`${key} = "(.*?)"`);
      const match = reg.exec(search) || reg2.exec(search);
      if (match) {
        formData[key] = match[1];
      }
    }
  });
  form.value = formData;
};

// 监听 display 变化
watch(
  () => props.display,
  (value) => {
    if (value) {
      setForm();
    }
  },
);
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.form {
  width: 80%;
  margin: 0 auto;
}

:deep(.size) {
  width: 100%;
}
</style>
